__author__ = 'vincent LIU'

import  os
import  pandas as pd
import time
import functools

disk_drive = "z:"
dpx_path = disk_drive + "/data/WindDB/dpx/"
outputpath = disk_drive + "/personal/yliu/test/"

def OutPutFd(qnum):
	outputdir = outputpath + "{0}/".format(qnum)
	if not os.path.exists(outputdir):
		os.mkdir(outputdir)
	outputname  = outputdir + "{0}.output.csv".format(qnum)
	fd = open(outputname,"w+")
	return fd

def OutPutName(qnum):
	outputdir = outputpath + "{0}/".format(qnum)
	if not os.path.exists(outputdir):
		os.mkdir(outputdir)
	outputname  = outputdir + "{0}.output.csv".format(qnum)
	return outputname

def OutputList(alist,qry_str):
	fd = OutPutFd(qry_str)
	for dates in alist:
		fd.write("{0}\n".format(dates))
	fd.close()

def OutputQ1(alist):
	weekday_list = [0,]*7
	for date in alist:
		curdate = time.strptime(date,"%Y%m%d")
		weekday_list[curdate.tm_wday]+=1
	fd = OutPutFd("Q1")
	fd.write("trading day num,%d\n"% len(alist))
	for i in range(len(weekday_list)):
		fd.write("%d,%d\n"% (i,weekday_list[i]))
	fd.close()

class DataCalc:
	def __init__(self):
		self.tdates_list = []

	'''Q1 answer '''
	def GetTradingDates(self,fromdate,todate):
		dates_list = os.listdir(dpx_path)
		cnt = 0
		for k in dates_list:
			if len(k)!=16:
				continue
			if k[0:8]>=fromdate:
				if k[0:8]<=todate:
					cnt+=1
					self.tdates_list.append(k[0:8])
				else:
					break
		return self.tdates_list

	'''Q2 answer '''
	def UnionStocks(self,fromdate,todate):
		self.GetTradingDates(fromdate,todate)
		tk_union_set = set()
		for dates in self.tdates_list:
			fname = dpx_path + dates +".dpx.csv"
			df = pd.read_csv(fname,dtype={'#TICKER':str},usecols=['#TICKER'])
			cur_set = set(df['#TICKER'].tolist())
			tk_union_set = tk_union_set.union(cur_set)
		tk_union_list = list(tk_union_set)
		tk_union_list = sorted(tk_union_list)
		return  tk_union_list

	'''Q3 answer '''
	def CrossStarsStock(self):
		ret_df = pd.DataFrame()
		o_name = OutPutName("Q3")
		for dates in self.tdates_list:
			fname = dpx_path + dates +".dpx.csv"
			df = pd.read_csv(fname,dtype={'#TICKER':str},usecols=['#TICKER','DATE_','LOW','HIGH'])
			cur_df = df[df['HIGH']==df['LOW']]
			ret_df = ret_df.append(cur_df,ignore_index=True)
#		ret_df = ret_df['#TICKER','DATE_','LOW','HIGH']
		ret_df.to_csv(o_name,mode="w",index=False)

	'''Q4 answer'''
	def StockReturn(self,fromdate,todate):
		self.GetTradingDates(fromdate,todate)
		close_df = pd.DataFrame()
		ldate = ""
		for cdate in self.tdates_list:
			fname = dpx_path + cdate +".dpx.csv"
			df = pd.read_csv(fname,usecols=['#TICKER','CLOSE'])
			df['#TICKER'] = df['#TICKER'].apply(lambda x: '{0:>06}'.format(x))
			df=df.set_index('#TICKER')
			df = df.rename(columns={'CLOSE':cdate})
			close_df = pd.concat([close_df,df[cdate]],axis=1)

			close_df = close_df.fillna(0)
			'''get last good close'''
			# if cdate == self.tdates_list[0]:
			# 	ldate = cdate
			# 	continue
			# else:
			# 	tk_list = (close_df[cdate]==0)
			# 	close_df.loc[tk_list,cdate] = close_df.loc[tk_list,ldate]
			# 	ldate = cdate

		return_df = pd.DataFrame()
		for cdate in self.tdates_list:
			if cdate == self.tdates_list[0]:
				return_df = pd.concat([return_df,close_df[cdate]],axis=1)#FIXME:that right?
				return_df[cdate]=1
				ldate = cdate
				pass
			else:
				tmpcls = close_df[close_df[ldate]!=0]
				df_col = close_df[cdate]/tmpcls[ldate]
				df_col = df_col.round(decimals=4)
				df_col[df_col==0]=1
				df_col.fillna(1,inplace=True)
				df_col = df_col.apply(lambda x:"{0:.4f}".format(x))
				df = df_col.to_frame(cdate)
				#df = 'r'+df
				return_df = pd.concat([return_df,df],axis=1)
				ldate = cdate
		#return_df.fillna(value=1,inplace=True)
		return_df  = return_df.T
		o_name = OutPutName("Q4")
		return_df.to_csv(o_name,mode="w")
		return return_df

'''
new:Q6 amswer method
old:Q5 answer method 1
'''
def fibonacci(n):
	a, b = 1, 1
	for i in range(0, n):
		tmp = a
		a = b
		b = tmp + b
		#a, b = b, a + b
	return a

'''Q5 answer way method 2'''
def fib(n):
	def m1(a,b):
		m=[[],[]]
		m[0].append(a[0][0]*b[0][0]+a[0][1]*b[1][0])
		m[0].append(a[0][0]*b[0][1]+a[0][1]*b[1][1])
		m[1].append(a[1][0]*b[0][0]+a[1][1]*b[1][0])
		m[1].append(a[1][0]*b[1][0]+a[1][1]*b[1][1])
		return m
	def m2(a,b):
		m=[]
		m.append(a[0][0]*b[0][0]+a[0][1]*b[1][0])
		m.append(a[1][0]*b[0][0]+a[1][1]*b[1][0])
		return m
	return m2(functools.reduce(m1,[[[0,1],[1,1]] for i in range(n)]),[[1],[1]])[0]

'''
new:Q7
old:Q6 answer
'''
def largestContinuousSum(arr):
	if len(arr)==0:
		return
	maxSum = currentSum = arr[0]
	start = tstart = end = 0
	for pos in range(1, len(arr)):
		if(arr[pos] > currentSum + arr[pos]):
			tstart = pos
			currentSum = arr[pos]
		else:
			currentSum += arr[pos]
		if(currentSum > maxSum):
			maxSum = currentSum
		start = tstart
		end = pos
	return [start,end,arr[start],arr[end],maxSum]

'''Q7 answer '''
'''
x^(x^(x^(x…) )…=2
f(x) = x^(x^(x^(x…) )
x^f(x)=x^(x^(x^(x…) )=2
x^2=2
x=√2
'''

'''Q8 answer'''
def threeSum(num):
	if len(num) <= 2:
		return []
	ret = []
	tar = 0
	num.sort()
	i = 0
	while i < len(num) - 2:
		j = i + 1
		k = len(num) - 1
		while j < k:
			if num[i] + num[j] + num[k] < tar:
				j += 1
			elif num[i] + num[j] + num[k] > tar:
				k -= 1
			else:
				ret.append([i,j,k,num[i], num[j], num[k]])
				j += 1
				k -= 1
				# folowing 3 while can avoid the duplications
				while j < k and num[j] == num[j - 1]:
					j += 1
				while j < k and num[k] == num[k + 1]:
					k -= 1
		while i < len(num) - 2 and num[i] == num[i + 1]:
			i += 1
		i += 1
	return ret

def OutputQ8():
	fd = open("A.csv",'r')
	a8 = []
	for k in  fd.readlines():
		a8.append(int(k.strip('\n')))
	# print(a8)
	fd.close()
	a8out=(threeSum(a8))
	fd = open("Q8.out.csv","w+")
	fd.write("#i,j,k,ai,aj,ak\n")
	for l in a8out:
		fd.write("%d,%d,%d,%d,%d,%d\n" % (l[0],l[1],l[2],l[3],l[4],l[5]))
	fd.close()

def OutputQ6():
	fd = open("A.csv",'r')
	a6 = list()
	for k in fd.readlines():
		a6.append(int(k.strip('\n')))
	fd = open("Q6.out.csv","w+")
	fd.write("#n,value\n")
	fd.write("10,%s\n" % (fib(10)))
	fd.write("20,%s\n" % (fib(20)))
	fd.write("50,%s\n" % (fib(50)))
	fd.write("100,%s\n" % (fib(100)))
	fd.write("500,%s\n" % (fib(500)))
	fd.close()

def OutputQ7():
	fd = open("A.csv",'r')
	a7 = list()
	for k in fd.readlines():
		a7.append(int(k.strip('\n')))
	fd.close()
	fd = open("Q7.out.csv","w+")
	fd.write("#startingIndex,endingIndex,staringValue,endingValue,sum\n")
	out = largestContinuousSum(a7)
	fd.write("%d,%d,%d,%d,%d\n" % (out[0],out[1],out[2],out[3],out[4]))
	fd.close()


if __name__ == "__main__":
	start = time.clock()
	dc = DataCalc()
	OutputQ7()
	# q1=dc.GetTradingDates("20100101","20150925")
	# OutputQ1(q1)
	# q2 = dc.UnionStocks("20100101","20150925")
	# OutputList(q2,"Q2")
	# dc.CrossStarsStock()
	# dc.StockReturn("20100101","20150925")
	#q5 = fibonacci(50000)
	#print(q5)
	# OutputList([q5],"Q5")
	# a=[-3,4,-2,99]
	# q6=largestContinuousSum(a)
	# OutputList([q6],"Q6")
	#a8=[-85,-61,-70,-76,68,40,34,99,-94,-1,-73,-11,-42,-62,-15,-97,-26,-31,-18,-35,-64,
	    # -96,79,24,-19,61,56,-58,-80,-22,-71,77,-46,16,-13,-43,-40,-69,-50,8,3,-4,98,-60,
	    # -89,-84,17,-7,20,81,69,25,67,-72,65,89,-12,-27,-54,-81,48,59,19,-41,-3,60,-67,6,
	    # 23,28,94,55,85,52,-28,-33,-92,44,-25,-66,-56,-83,-88,-23,-45,71,-95,-48,-32,-59,12,-53,91,-2,18,-16,-38,-49,92,-93]

	end = time.clock()
	print(end-start)